package com.base.designpattern.builder;

/**
 *  变种 构造器模式
 */
public class OptimizedBuilderPatternDemo {

	public static void main(String[] args) {
		Product product = new ConcreteBuilder()
				.field1("值1")
				.field2("值2")
				.field3("值3")
				.create();
		System.out.println(product);

		// 现在基本上流行的一些开源框架，构造器模式的运用，一般都是上面这种变种模式

		/**
		 * 构造器是一种非常棒，非常实用，非常常用的设计模式，大家务必要掌握好
		 *
		 * 常见于在构建一个复杂的对象，或者是构建一个复杂的表达式的时候，在开源框架中有大量广泛的运用
		 *
		 * 给大家举个例子，Mockito框架中，when().thenReturn()之类的，
		 * 其实就是构造器模式的一种，通过多个连续的方法完成一个模拟对象的构建；还有就是spring test框架汇总，MvcMock对象，
		 * 也是通过thenExpected()等多个连续的方法，完成一个mvc测试对象的构建，
		 * 这块我们首先在后面spring boot源码剖析的时候会带着大家来阅读这些源码，掌握实践。
		 * 同时在阶段一的电商系统设计中，我们对于一些复杂对象的构建，
		 * 给大家举个例子，比如说销售出库单的构建，如此复杂的对象，采用构造器模式是非常合适的
		 *
		 * 用构造器模式的最大好处是啥？复杂对象的构建过程太复杂了，里面可能包含一些业务逻辑，比如值检查，格式转换之类的。
		 * 如果每个客户端都自己手动去完成构建的话，那么大量的冗余代码是一个；另外一个，如果我们要改变对象的构建过程的实现，
		 * 可以就在构造器中一个地方修改即可，对于调用方完全透明；最后，如果我们要完全替换掉以前的builder实现的话，
		 * 那么完全可以在工厂里替换一个实现，还跟简单工厂模式结合起来使用了
		 */
	}

	public static class Product {

		private String field1;
		private String field2;
		private String field3;

		public String getField1() {
			return field1;
		}
		public void setField1(String field1) {
			this.field1 = field1;
		}
		public String getField2() {
			return field2;
		}
		public void setField2(String field2) {
			this.field2 = field2;
		}
		public String getField3() {
			return field3;
		}
		public void setField3(String field3) {
			this.field3 = field3;
		}

		@Override
		public String toString() {
			return "Product [field1=" + field1 + ", field2=" + field2 + ", field3=" + field3 + "]";
		}

	}

	public interface Builder {

		Builder field1(String value);
		Builder field2(String value);
		Builder field3(String value);
		Product create();

	}

	public static class ConcreteBuilder implements Builder {

		private Product product = new Product();

		public Builder field1(String value) {
			System.out.println("在设置field1之前进行复杂的校验逻辑");
			product.setField1(value);
			return this;
		}

		public Builder field2(String value) {
			System.out.println("在设置field2之前进行复杂的数据格式转化逻辑");
			product.setField2(value);
			return this;
		}

		public Builder field3(String value) {
			System.out.println("在设置field3之前进行复杂的数据处理逻辑，跟其他对象的数据进行关联");
			product.setField3(value);
			return this;
		}

		public Product create() {
			return product;
		}

	}

}
